﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Objects.DataClasses;

namespace Server
{
    public class DB
    {

        public DB()
        {
            
        }

        public UserEntity getUser(String email, String password)
        {
            using (DBConfig db = new DBConfig())
            {
                var user = (from u in db.users
                           where u.email == email && u.password == password
                           select u).FirstOrDefault();
                return user;
            }
        }

        public SessionEntity getSession(UserEntity u)
        {
            using (DBConfig db = new DBConfig())
            {
                var session = (from s in db.sessions
                              where s.user == u.id
                              select s).FirstOrDefault();
                return session;
            }
        }

        public SessionEntity getSession(String session_id)
        {
            using (DBConfig db = new DBConfig())
            {
                var session = (from s in db.sessions.Include("user1")
                              where s.id == session_id
                              select s).FirstOrDefault();
                if (session != null)
                {
                    if (session.version == (int)ServiceDevice.Silverlight)
                    {
                        if (session.date < DateTime.Now.AddMinutes(-20))
                        {
                            db.DeleteObject(session);
                            db.SaveChanges();
                            return null;
                        }
                    }
                    session.date = DateTime.Now;
                    db.SaveChanges();
                }
                return session;
            }
        }

        public RegistrationEntity getRegistration(UserEntity u, RssFeed rss_feed)
        {
            using(DBConfig db = new DBConfig())
            {
                var registration = (from r in db.registrations
                                    where r.channel == rss_feed.id && r.user == u.id
                                    select r).FirstOrDefault();
                return registration;
            }
        }

        public ChannelEntity getChannel(int channel_id)
        {
            using (DBConfig db = new DBConfig())
            {
                var channel = (from c in db.channels
                                    where c.id == channel_id
                                    select c).FirstOrDefault();
                return channel;
            }
        }

        public ChannelEntity getChannel(String url)
        {
            using (DBConfig db = new DBConfig())
            {
                var channel = (from c in db.channels.Include("items")
                               where c.url == url
                               select c).FirstOrDefault();
                return channel;
            }
        }

        public List<RssFeed> getChannels(UserEntity u)
        {
            using (DBConfig db = new DBConfig())
            {
                var registrations = (from r in db.registrations
                                     where r.user == u.id
                                     select r);
                if (registrations.Count() == 0)
                    return null;
                else
                {
                    List<RssFeed> list = new List<RssFeed>();
                    foreach (RegistrationEntity r in registrations)
                    {
                        list.Add(ConvertEntityModel.ToRssFeed(r.channel1));
                    }
                    return list;
                }
            }
        }

        public List<RssFeed> getPublicChannels(UserEntity u)
        {
            using (DBConfig db = new DBConfig())
            {
                var channels = (from c in db.channels
                                where !(from r in db.registrations
                                        where r.user == u.id
                                        select r.channel).Contains(c.id)
                                select c);
                if (channels.Count() == 0)
                    return null;
                else
                {
                    List<RssFeed> list = new List<RssFeed>();
                    foreach (ChannelEntity chan in channels)
                    {
                        list.Add(ConvertEntityModel.ToRssFeed(chan));
                    }
                    return list;
                }
            }
        }

        public List<RssFeedItem> getItems(RssFeed rss_feed, UserEntity u)
        {
            using (DBConfig db = new DBConfig())
            {
                var items = (from i in db.items
                            where i.channel == rss_feed.id
                            select i);
                if (items.Count() == 0)
                    return null;
                else
                {
                    List<RssFeedItem> list = new List<RssFeedItem>();
                    foreach (ItemEntity i in items)
                    {
                        list.Add(ConvertEntityModel.ToRssFeedItem(i, u));
                    }
                    return list;
                }
            }
        }

        public List<RssFeedItem> getLastItems(UserEntity u, bool no_read = false)
        {
            using (DBConfig db = new DBConfig())
            {
                IQueryable<ItemEntity> items;
                if (!no_read)
                {
                    items = (from i in db.items
                             join r in db.registrations on i.channel equals r.channel
                             where r.user == u.id
                             orderby i.date descending
                             select i).Take(10);
                }
                else
                {
                    items = (from i in db.items
                             join r in db.registrations on i.channel equals r.channel
                             where r.user == u.id &&
                                 !(from s in db.itemStates
                                   where s.user == u.id &&
                                   s.readState == true
                                   select s.item).Contains(i.id)
                              orderby i.date descending
                              select i).Take(10);
                }
                if (items.Count() == 0)
                    return null;
                else
                {
                    List<RssFeedItem> list = new List<RssFeedItem>();
                    foreach (ItemEntity i in items)
                    {
                        list.Add(ConvertEntityModel.ToRssFeedItem(i, u));
                    }
                    return list;
                }
            }
        }

        public ItemStateEntity getItemState(RssFeedItem item, UserEntity user)
        {
            using (DBConfig db = new DBConfig())
            {
                var state = (from s in db.itemStates
                             where s.item == item.id && s.user == user.id
                             select s).FirstOrDefault();
                return state;
            }
        }

        public bool deleteSession(String session_id)
        {
            using (DBConfig db = new DBConfig())
            {
                var session = (from s in db.sessions
                              where s.id == session_id
                              select s).FirstOrDefault();
                if (session == null)
                    return false;
                else
                {
                    db.DeleteObject(session);
                    db.SaveChanges();
                    return true;
                }
            }
        }

        public SessionEntity createSession(UserEntity u, ServiceDevice version)
        {
            using (DBConfig db = new DBConfig())
            {
                SessionEntity s = new SessionEntity();
                s.user = u.id;
                s.date = DateTime.Now;
                s.version = (int)version;
                db.AddTosessions(s);
                db.SaveChanges();
                return s;
            }
        }

        public RegistrationEntity createRegistration(RssFeed rss_feed, UserEntity u)
        {
            using (DBConfig db = new DBConfig())
            {
                RegistrationEntity r = new RegistrationEntity();
                r.channel = rss_feed.id;
                r.date = DateTime.Now;
                r.user = u.id;
                db.AddToregistrations(r);
                db.SaveChanges();
                return r;
            }
        }

        public ChannelEntity createChannel(ChannelEntity channel)
        {
            using (DBConfig db = new DBConfig())
            {
                db.AddTochannels(channel);
                db.SaveChanges();
                return channel;
            }
        }

        public ItemStateEntity createItemState(RssFeedItem item, UserEntity u, bool read)
        {
            using (DBConfig db = new DBConfig())
            {
                ItemStateEntity state = new ItemStateEntity();
                state.user = u.id;
                state.item = item.id;
                state.readState = read;
                db.AddToitemStates(state);
                db.SaveChanges();
                return state;
            }
        }

        public ChannelEntity updateChannel(ChannelEntity chan, EntityCollection<ItemEntity> list)
        {
            using (DBConfig db = new DBConfig())
            {
                foreach(ItemEntity item in list){
                   
                    item.channel = chan.id;
                    db.AddToitems(item);
                }
                db.SaveChanges();
                return chan;
            }
        }

        public ItemStateEntity updateItemState(ItemStateEntity state, bool read)
        {
            using (DBConfig db = new DBConfig())
            {
                var i = (from s in db.itemStates
                             where s.id == state.id
                             select s).FirstOrDefault();
                if (i != null)
                {
                    i.readState = read;
                    db.SaveChanges();
                    return i;
                }
                return null;
            }
        }
    }
}